<?php

/**
 * MyDb
 *
 * Classe que ira ministrar todas as conexoes com o banco de dados
 *
 * @author  Richard Brandao <richardsbrandao@gmail.com>
 * @since   2011-06-22
 */

class MyDb extends Db implements Serializable {

    /**
     * @static  @var    MyDb    $tInstance
     * SingleTon, retorna a instancia da propria classe
     */
    private static $tInstance;
    /**
     * @var boolean     $BoTransaction
     * Informa se a transacao esta iniciada ou nao
     */
    private $BoTransaction = false;
    /**
     * @var boolean     BoCommitTransaction
     * Informa se a transacao deve ser comitada ou nao. Null se ainda nao foi
     * iniciada nenhuma transacao
     */
    private $BoCommitTransaction = null;

    /**
     * @method  getInstance
     * Retorna a instancia de um objeto MyDb caso ela já esteja instanciada ou
     * caso contrario inicia uma propria instancia da classe
     *
     * @since   2011-06-22
     * @return  Object MyDb
     */
    public static function getInstance() {
        if( !is_object(self::$tInstance) ) {
            self::$tInstance = new MyDb();
        }
        return self::$tInstance;
    }

    /**
     * @method  getConnection
     *
     * Abre e retorna um objeto de conexao mysqli com o banco
     *
     * @param   string  $StHost         Host de conexao com o banco
     * @param   string  $StUser         Usuario de conexao com o banco
     * @param   string  $StPass         Senha de conexao com o banco
     * @param   string  $StDatabase     Banco que sera conectado
     *
     * @since   2011-11-14
     * @author  Richard Brandao <richardsbrandao@gmail.com>
     * @return  Resoure
     */
    public function getConnection($StHost, $StUser, $StPass, $StDatabase) {
        if( !parent::getDbConnection()) {
            $this->connect($StHost, $StUser, $StPass, $StDatabase);
        }
        return parent::getDbConnection();
    }

    /**
     * @method  connect
     * Connecta com um banco de dados Mysql através da Extensao Mysqli do php
     *
     * @param string $StHost        Host de Conexao com o servidor
     * @param string $StUser        Usuario de Conexao com o servidor
     * @param string $StPass        Senha de acesso ao servidor
     * @param string $StDatabase    Banco de dados que sera utilizado na operacao
     *
     * @since   2011-06-22
     * @return  boolean
     * @author  Richard Brandao <richardsbrandao@gmail.com>
     */
    private function connect($StHost, $StUser, $StPass, $StDatabase) {
        parent::setHost($StHost);
        parent::setUser($StUser);
        parent::setPass($StPass);
        parent::setDatabase($StDatabase);
        parent::setDbConnection( new mysqli($StHost, $StUser, $StPass, $StDatabase) );
    }

    /**
     * @method  selectDb
     * Troca o nome e seleciona um novo banco de dados.
     *
     * @since   2011-06-22
     * @return  boolean
     * @see     Veja os metodos get/set para alteracao das propridades das classes
     */
    public function selectDb() {
        return parent::getDbConnection()->select_db(parent::getDatabase());
    }

    /**
     * @method  close
     * Encerra uma conexao com o banco de dados mysqli
     *
     * @since   2011-06-22
     * @return  boolean
     */
    public function close() {
        if( !parent::getDbConnection() ) {
            return false;
        }
         parent::getDbConnection()->close();
         parent::setDbConnection(null);
         return true;
    }
    /**
     * @method  exec
     * Executa uma consulta ao banco de dados conectado
     *
     * @param   string  $query  Consulta ou Acao que sera realizada no banco
     *
     * @since   2011-06-23
     * @return  Object Query
     */
    public function exec($query) {
        $tQuery = parent::getDbConnection()->query($query);
        parent::setQuery($tQuery);
        $this->transactionManager();
        return parent::getQuery();
    }

    /**
     * @method  fetchAll
     * Retorna todos os resultados em um array associativo da ultima consulta
     * realizada pelo metodo exec.
     *
     * @since   2011-06-24
     * @return  array
     */
    public function fetchAll() { //Limite, Começar a partir do ..., Tipo de Indice (Contador ou alguma coisa da tabela)
        while( $ArLine = mysqli_fetch_assoc(parent::getQuery()) ) {
            $ArRetorno[] = $ArLine;
        }
        return isset($ArRetorno) ? $ArRetorno : false ;
    }

    /**
     * @method  numRows
     * Retorna o numero de linhas na ultima consulta ao banco de dados feita por
     * exec.
     *
     * @since   2011-06-23
     * @return  integer
     */
    public function numRows() {
        return parent::getQuery()->num_rows;
    }

    /**
     * @method  result
     * Simula a funcao mysql_result. Retorna a $ItRow linha da ultima consulta
     * feita ao banco de dados. Caso $StField nao seja passada result ira retornar
     * um array contendo toda a linha, caso contrario, o campo $StField da linha
     * $ItRow sera o resultado final
     *
     * @param integer $ItRow    Numero da linha da consulta
     * @param string  $StField  Campo utilizado na consulta
     *
     * @since   2011-06-24
     * @return  mixed (array/string)
     */
    public function result($ItRow, $StField = false) {
        $tPointer = parent::getQuery()->data_seek($ItRow);
        $ArFetch = parent::getQuery()->fetch_assoc();
        return empty($StField) ? $ArFetch : $ArFetch[$StField];
    }
    /**
     * @method  lastInsertId
     * Retorna o ID da ultima insercao ao banco de dados.
     *
     * @since   2011-06-24
     * @return  integer
     */
    public function lastInsertId() {
        return parent::getDbConnection()->insert_id;
    }

    /**
     * @method  affectedRows
     * Retorna o numero de linhas afetadas atraves da ultima chamada por this->exec
     *
     * @since   2011-07-18
     * @return  integer
     */
    public function affectedRows() {
        return parent::getDbConnection()->affected_rows;
    }

    /**
     * @method  lastQueryReturn
     * Diz se a ultima query executada foi um sucesso.
     *
     * @since   2011-10-23
     * @return  boolean
     */
    public function lastQueryReturn() {
        return $this->affectedRows() > -1 ? true : false;
    }
    //20-12
    /**
     * @method  beginTransaction
     *
     * Inicia uma nova transacao no banco de dados
     *
     * @since   2011-12-20
     * @return  void
     */
    public function beginTransaction() {
        $this->BoTransaction = true;
        $this->BoCommitTransaction = true;
        parent::getDbConnection()->autocommit(false);
    }
    /**
     * @method  endTransaction
     *
     * Termina uma transacao no banco de dados, da o commit se todas as queries
     * tenham sido sucesso ou rollback se alguma falhou
     *
     * @return  void
     * @since   2011-12-20
     */
    public function endTransaction() {
        if($this->BoCommitTransaction) {
            parent::getDbConnection()->commit();
        } else {
            parent::getDbConnection()->rollback();
        }
        parent::getDbConnection()->autocommit(true);
    }
    /**
     * @method  lastTransactionReturn
     *
     * Retorna o resultado da ultima transacao
     *
     * @return  boolean
     * @since   2011-12-20
     */
    public function lastTransactionReturn() {
        return $this->BoCommitTransaction;
    }
    /**
     * @method  transactionManager
     *
     * Gerenciador de transacao de transacoes, se nao estiver ativada retorna null
     * se estiver, manipula o retorno e diz se a transacao deve ser comitada ou nao
     *
     * @since   2011-12-20
     * @return  void
     */
    private function transactionManager() {
        if(!$this->BoTransaction) {return null;}
        if( $this->lastQueryReturn() && ($this->BoCommitTransaction || is_null($this->BoCommitTransaction)) ) {
            $this->BoCommitTransaction = true;
        } else {
            $this->BoCommitTransaction = false;
        }
    }

    public function isCommitable() {
        return $this->BoCommitTransaction;
    }

    /**
     * Serializa o objeto MyDb
     *
     * @since   2012-01-16
     * @return  string
     */
    public function serialize() {
        return serialize(array(parent::getHost(), parent::getUser(),parent::getPass(), parent::getDatabase()));
    }

    /**
     * @method  unserialize
     *
     * Reconstroi o objeto depois de ser serializado
     *
     * @param string $serialized
     *
     * @since   2012-01-16
     * @return  void
     */
    public function unserialize($serialized) {
        $ArDados = unserialize($serialized);
        parent::setHost($ArDados[0]);
        parent::setUser($ArDados[1]);
        parent::setPass($ArDados[2]);
        parent::setDatabase($ArDados[3]);
    }

}

?>
